﻿namespace TapMe.ViewModel
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel;
    using System.Windows.Input;
    using System.Threading;

    using GalaSoft.MvvmLight;
    using GalaSoft.MvvmLight.Command;
    using GalaSoft.MvvmLight.Messaging;

    using TapMe.Model;
    using TapMe.Lib;

    public class ViewModel : ViewModelBase, INotifyPropertyChanged
    {

        #region Constants

        private const string GAME_PLAY_PAGE = "/View/GamePlayPage.xaml";

        #endregion

        private const double FALSE_PROBABILITY = 0.1;
        private const int MAX_FINGER = 3;
        private const int NUM_PT_TYPES = 2;
        private const long POINT_DISPLAY_PERIOD = 1000;

        /// <summary>
        /// The game model
        /// </summary>
        private Model gameModel;

        private IList<PatternPt> patternQueue;

        // maps the number of fingers to color
        private IDictionary<int, String> numFingersToColor;
        
        // current index into the patternQueue list. The index
        // will be advanced after the corresponding point is 
        // displayed
        private int patternQueueIndex;

        // the color of the currrent point being displayed
        public string currentPoint { get; set; }
        public bool hasNextPattern { get; set; }
        

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// For changing the pattern every some interval
        /// </summary>
        private Timer patternTrigger;

        #region ICommands

        public ICommand LevelSelectionTapEventHandler
        {
            get;
            private set;
        }
    
        #endregion

        /// <summary>
        /// Initializes the ViewModel and hook the handler up with the model
        /// </summary>
        public ViewModel()
        {
            #region populate color dictionary
            numFingersToColor = new Dictionary<int, String>();
            numFingersToColor.Add(0, "Cyan");
            numFingersToColor.Add(1, "Purple");
            numFingersToColor.Add(2, "Green");
            #endregion
                      
            this.patternQueueIndex = 0;

            // initialize a new timer (not started yet)
            this.patternTrigger = new Timer(this.patternTriggerCallBack);

            gameModel = Model.getModelInstance(NUM_PT_TYPES, MAX_FINGER, FALSE_PROBABILITY);
            gameModel.verificationTimeoutEventHandler += new EventHandler(HandleTaskOverSignal);
            LevelSelectionTapEventHandler = new RelayCommand<string>((Tag) => TapEventHandler(Tag));
        }

        // Create the OnPropertyChanged method to raise the event 
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        // starts the level
        public void startGamePlay()
        {
            this.gameModel.startLevel(1);
            this.patternQueue = this.gameModel.generatePattern();
            displayCurrentPatternAndStartTask();

            //TODO: more to come..
        }

        // callback function for the patternTrigger Timer
        // sets the current point color corresponding to the current PatternPt
        // and advances the index into the pattern queue by one
        private void patternTriggerCallBack(object state)
        {
            // pause the timer and start the task when all the points have been displayed
            if (patternQueueIndex >= patternQueue.Count)
            {
                this.patternTrigger.Change(Timeout.Infinite, Timeout.Infinite);
                gameModel.startTask();
            }

            currentPoint = numFingersToColor[patternQueue[patternQueueIndex].numFingers];
            patternQueueIndex++;
        }

        // Display the current pattern. After the pattern is displayed, the task will start
        private void displayCurrentPatternAndStartTask()
        {
            this.patternQueueIndex = 0;
            // star the timer
            patternTrigger.Change(0, POINT_DISPLAY_PERIOD);
        }

        #region Event Handler
        /// <summary>
        /// Handles when the player fails to complete the task
        /// </summary>
        /// <param name="sender">the method sender</param>
        /// <param name="e">the event arguments</param>
        private void HandleTaskOverSignal(object sender, EventArgs e)
        {
            // Impl details: we should move to the next task here.
        }

        private void TapEventHandler(string level)
        {
            GoToPageMessage message = new GoToPageMessage() { PageName = GAME_PLAY_PAGE };
            Messenger.Default.Send<GoToPageMessage>(message);
        }

        #endregion

    }
}